from functools import wraps
from flask import Blueprint, jsonify, redirect, render_template, request, session, url_for
from app.admin.utils import admin_required
from app.doctor.utils import doctor_required_web, doctor_required
from app.models import db
from app.doctor.models import Doctor
from app.admin.models import Admin
from app.models import *
from app.utils import process_request_data

doctor = Blueprint('doctor', __name__, template_folder='templates')


@doctor.route('/query_doctor', methods=['POST'])
@admin_required
def query_doctor():
    # process data
    data = process_request_data(request)

    # query doctors
    try:
        doctors = Doctor.query.filter_by(**data).all()
    except:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400
    # return doctors
    return jsonify({"code": 0, 'message': 'success', 'data': [doctor.to_dict() for doctor in doctors]})


@doctor.route('/login_doctor', methods=['POST'])
def login_doctor():
    data = process_request_data(request)
    username = data.get('username')
    password = data.get('password')

    doctor = Doctor.query.filter_by(username=username).first()
    if doctor and doctor.check_password(password):
        # Valid credentials, set session or token for authentication
        # Example of storing doctor id in session
        session['doctor_id'] = doctor.id
        session['username'] = doctor.username
        return jsonify({"code": 0, 'message': 'Login successful'})
    else:
        return jsonify({"code": 1, 'message': 'Invalid username or password'}), 401


@doctor.route('/delete_doctor', methods=['POST'])
@admin_required
def delete_doctor():
    # process data
    data = process_request_data(request)
    doctor = Doctor.query.filter_by(id=data.get('id')).first()
    if doctor is None:
        return jsonify({"code": 1, 'message': 'Doctor not found'}), 404
    db.session.delete(doctor)
    db.session.commit()
    return jsonify({"code": 0, 'message': 'Doctor deleted successfully'})


@doctor.route('/logout_doctor', methods=['POST'])
@doctor_required
def logout_doctor():
    session.pop('username', None)
    session.pop('doctor_id', None)
    return jsonify({"code": 0, 'message': 'Logout successful'})


@doctor.route('/add_doctor', methods=['POST'])
@admin_required
def add_doctor():
    # process data
    data = process_request_data(request)
    username = data.get('username')
    password = data.get('password')
    name = data.get('name')
    if username is None or password is None:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    # check if doctor exists
    if Doctor.query.filter_by(username=username).first():
        return jsonify({"code": 1, 'message': 'Doctor already exists'}), 400
    new_doctor = Doctor(username, password)
    if name:
        new_doctor.name = name
    db.session.add(new_doctor)
    try:
        db.session.commit()
    except:
        return jsonify({"code": 1, 'message': 'Error adding doctor'}), 500
    return jsonify({"code": 0, 'message': 'Doctor added successfully', "data": {"id": new_doctor.id, "username": new_doctor.username}})


@doctor.route('/modify_doctor', methods=['POST'])
@admin_required
def modify_doctor():
    # process data
    data = process_request_data(request)
    doctor = Doctor.query.filter_by(session['doctor_id']).first()
    if data.get('id') and data.get('id') != doctor.id:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400
    if doctor is None:
        return jsonify({"code": 1, 'message': 'Doctor not found'}), 404
    try:
        doctor.modify(**data)
    except:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 500
    db.session.commit()
    return jsonify({"code": 0, 'message': 'Doctor modified successfully'})

# 体检项目(item)增删改查


@doctor.route('/add_item', methods=['POST'])
@doctor_required
def add_item():

    # process data
    data = process_request_data(request)
    content = data.get('content')
    if content is None:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400
    new_item = Item(content)
    db.session.add(new_item)
    try:
        db.session.commit()
    except:
        return jsonify({"code": 1, 'message': 'Error adding item'}), 500
    return jsonify({"code": 0, 'message': 'Item added successfully', "data": {"id": new_item.id, "content": new_item.content}})


@doctor.route('/modify_item', methods=['POST'])
@doctor_required
def modify_item():
    # process data
    data = process_request_data(request)
    item_id = process_request_data(request).get('item_id')
    content = process_request_data(request).get('content')
    if item_id is None or content is None:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    item = Item.query.get(item_id)
    if not item:
        return jsonify({"code": 1, 'message': 'Item not found'}), 404

    item.content = content
    db.session.commit()
    return jsonify({"code": 0, 'message': 'Item modified successfully'})


@doctor.route('/delete_item', methods=['POST'])
@doctor_required
def delete_item():

    # process data
    data = process_request_data(request)
    item_id = data.get('item_id')
    if not item_id:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    item = Item.query.get(item_id)
    if not item:
        return jsonify({"code": 1, 'message': 'Item not found'}), 404

    db.session.delete(item)
    db.session.commit()
    return jsonify({"code": 0, 'message': 'Item deleted successfully'})


@doctor.route('/query_item', methods=['POST'])
def query_item():
    # process data
    data = process_request_data(request)
    try:
        items = Item.query.filter_by(**data).all()
    except:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 500
    return jsonify({"code": 0, 'message': 'Item queried successfully',
                    "data": [item.to_dict() for item in items]})

# 体检套餐(package)增删改查


@doctor.route('/add_package', methods=['POST'])
@doctor_required
def add_package():
    # process data
    data = process_request_data(request)
    name = data.get('name')
    description = data.get('description')
    item_ids_string = data.get('item_ids')
    if name is None or description is None or item_ids_string is None:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    package = Package(name=name, description=description)
    db.session.add(package)
    item_ids = [int(item_id) for item_id in item_ids_string.split(',')]

    try:
        # Add items to the package
        for item_id in item_ids:
            item = Item.query.get(item_id)
            if not item:
                db.session.delete(package)
                return jsonify({"code": 1, 'message': 'Item not found'}), 404
            package_item = PackageItem(package_id=package.id, item_id=item.id)
            db.session.add(package_item)

    except:
        db.session.rollback()
        return jsonify({"code": 1, 'message': 'Error adding items to the package'}), 500
    db.session.commit()
    return jsonify({"code": 0, 'message': 'Package added successfully'})


@doctor.route('/modify_package', methods=['POST'])
@doctor_required
def modify_package():

    # process data
    data = process_request_data(request)
    package_id = data.get('package_id')
    name = data.get('name')
    description = data.get('description')
    item_ids = data.get('item_ids')
    if package_id is None:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    package = Package.query.get(package_id)
    if not package:
        return jsonify({"code": 1, 'message': 'Package not found'}), 404

    if name:
        package.name = name
    if description:
        package.description = description

    # Remove existing items from the package
    PackageItem.query.filter_by(package_id=package_id).delete()

    # Add new items to the package
    for item_id in item_ids:
        item = Item.query.get(item_id)
        if not item:
            return jsonify({"code": 1, 'message': 'Item not found'}), 404
        package_item = PackageItem(package_id=package.id, item_id=item.id)
        db.session.add(package_item)

    db.session.commit()
    return jsonify({"code": 0, 'message': 'Package modified successfully'})


@doctor.route('/query_package', methods=['POST'])
def query_package():
    # process data
    data = process_request_data(request)
    try:
        packages = Package.query.filter_by(**data).all()
    except:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 500
    return jsonify({"code": 0, 'message': 'Package queried successfully', "data": [package.to_dict() for package in packages]})


@doctor.route('/query_package_items', methods=['POST'])
def query_package_items():
    # process data
    data = process_request_data(request)
    print(data)
    try:
        package_items = PackageItem.query.filter_by(**data).all()
        item_ids = [item.item_id for item in package_items]
        print(item_ids)
    except:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 500
    items = []
    for item_id in item_ids:
        item = Item.query.get(item_id)
        if not item:
            items.append({"id": item_id, "content": "Item not found"})
        else:
            items.append(item.to_dict())
    return jsonify({"code": 0, 'message': 'Package items queried successfully',
                    "data": items})


@doctor.route('/delete_package', methods=['POST'])
@doctor_required
def delete_package():

    # process data
    data = process_request_data(request)
    package_id = data.get('package_id')
    if not package_id:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    package = Package.query.get(package_id)
    if not package:
        return jsonify({"code": 1, 'message': 'Package not found'}), 404

    # Delete the package items
    PackageItem.query.filter_by(package_id=package_id).delete()
    db.session.delete(package)
    db.session.commit()
    return jsonify({"code": 0, 'message': 'Package deleted successfully'})

# 接受预约 拒绝预约 完成预约


@doctor.route('/complete_appointment', methods=['POST'])
@doctor_required
def complete_appointment():

    # process data
    data = process_request_data(request)
    appointment_id = data.get('appointment_id')
    if not appointment_id:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    appointment = Appointment.query.get(appointment_id)
    if not appointment:
        return jsonify({"code": 1, 'message': 'Appointment not found'}), 404

    if appointment.doctor_id != session['doctor_id']:
        return jsonify({"code": 1, 'message': 'Appointment does not belong to the doctor'}), 403

    if appointment.status != 'accepted':
        return jsonify({"code": 1, 'message': 'Appointment status is not accepted'}), 400

    appointment.status = "completed"
    db.session.commit()
    return jsonify({"code": 0, 'message': 'complete appointment successfully'})


@doctor.route('/accept_appointment', methods=['POST'])
@doctor_required
def accept_appointment():

    # process data
    data = process_request_data(request)
    appointment_id = data.get('appointment_id')
    if not appointment_id:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    appointment = Appointment.query.get(appointment_id)
    if not appointment:
        return jsonify({"code": 1, 'message': 'Appointment not found'}), 404

    if appointment.status != 'pending':
        return jsonify({"code": 1, 'message': 'Appointment status is not pending'}), 400

    appointment.status = 'accepted'
    appointment.doctor_id = session['doctor_id']
    db.session.commit()
    return jsonify({"code": 0, 'message': 'Appointment accepted successfully'})


@doctor.route('/reject_appointment', methods=['POST'])
@doctor_required
def reject_appointment():

    # process data
    data = process_request_data(request)
    appointment_id = data.get('appointment_id')
    if not appointment_id:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    appointment = Appointment.query.get(appointment_id)
    if not appointment:
        return jsonify({"code": 1, 'message': 'Appointment not found'}), 404

    if appointment.status != 'pending':
        return jsonify({"code": 1, 'message': 'Appointment status is not pending'}), 400

    appointment.status = 'rejected'
    appointment.doctor_id = session['doctor_id']
    db.session.commit()
    return jsonify({"code": 0, 'message': 'Appointment rejected successfully'})

# 获取预约列表


@doctor.route('/get_doctor_appointments', methods=['POST'])
@doctor_required
def get_doctor_appointments():

    # get appointments
    data = process_request_data(request)
    if "doctor_id" in data:
        if data.get("doctor_id") != session["doctor_id"]:
            return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    try:
        appointments = Appointment.query.filter_by(
            doctor_id=session['doctor_id'], **data).all()
    except:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400
    # format appointments
    appointments_list = []
    for appointment in appointments:
        appointment_dict = {
            'id': appointment.id,
            'patient_id': appointment.patient_id,
            'package_id': appointment.package_id,
            'appointment_time': appointment.appointment_time.strftime('%Y-%m-%d %H:%M:%S'),
            'status': appointment.status,
            'result': appointment.result
        }
        appointments_list.append(appointment_dict)

    return jsonify({'code': 0, 'data': appointments_list})


@doctor.route('/get_pending_appointments', methods=['POST', 'GET'])
@doctor_required
def get_pending_appointments():
    appointments = Appointment.query.filter_by(status='pending').all()
    return jsonify({"code": 0, 'message': 'Appointments retrieved successfully', 'data': [appointment.to_dict() for appointment in appointments]})

# 体检结果


@doctor.route('/update_result', methods=['POST'])
@doctor_required
def update_result():

    # process data
    data = process_request_data(request)
    appointment_id = data.get('appointment_id')
    result = data.get('result')
    if not appointment_id or not result:
        return jsonify({"code": 1, 'message': 'Invalid request'}), 400

    appointment = Appointment.query.get(appointment_id)
    if not appointment:
        return jsonify({"code": 1, 'message': 'Appointment not found'}), 404

    if appointment.doctor_id != session['doctor_id']:
        return jsonify({"code": 1, 'message': 'Appointment does not belong to the doctor'}), 403

    if appointment.status != 'accepted':
        return jsonify({"code": 1, 'message': 'Appointment status is not accepted'}), 400

    appointment.result = result
    db.session.commit()
    return jsonify({"code": 0, 'message': 'Result updated successfully'})

# 用于跳转的根路由


@doctor.route('/')
@doctor_required_web
def root_doctor():
    return redirect(url_for('doctor.dashboard_doctor_web'))

# 医生的用户面板 包含跳转按钮 -> /appointment_doctor_web ; /package_doctor_web


@doctor.route('/dashboard_doctor_web')
@doctor_required_web
def dashboard_doctor_web():
    return render_template('doctor/dashboard_doctor_web.html')


# 用于跳转的退出登陆路由
@doctor.route('/logout_doctor_web')
@doctor_required_web
def logout_doctor_web():
    session.pop('username', None)
    session.pop('doctor_id', None)
    return redirect(url_for('doctor.root_doctor'))

# 实际预约记录


@doctor.route('/appointment_doctor_web')
@doctor_required_web
def appointment_doctor_web():
    return render_template('doctor/appointment_doctor_web.html')


# 体检项目+体检套餐


@doctor.route('/package_doctor_web')
@doctor_required_web
def package_doctor_web():
    return render_template('doctor/package_doctor_web.html')


@doctor.route('/login_doctor_web')
def login_doctor_web():
    return render_template('doctor/login_doctor_web.html')
